// Author: Ivan Chau
package uk.ac.cam.kcic2.images;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.junit.Test;

import uk.ac.cam.kcic2.math.Vector3D;
import uk.ac.cam.kcic2.scene.Colour;


public class ImageComparator {

	@Test
	public void test() {
		String mayaPNG = "C:\\Users\\user\\Documents\\Computer Science\\PartII Project\\Maya\\images\\";
		String photonPNG = "C:\\Users\\user\\Documents\\Computer Science\\PartII Project\\Java\\workspace\\" +
				"Photon Mapping\\photon map images\\";
		String rayPNG = "C:\\Users\\user\\Documents\\Computer Science\\PartII Project\\Java\\workspace\\" +
				"Photon Mapping\\raytracer images\\";
		String rMDiffPNG = "C:\\Users\\user\\Documents\\Computer Science\\PartII Project\\Java\\workspace\\" +
				"Photon Mapping\\rMDiff\\";
		String pMDiffPNG = "C:\\Users\\user\\Documents\\Computer Science\\PartII Project\\Java\\workspace\\" +
				"Photon Mapping\\pMDiff\\";
		String rMDiff = "C:\\Users\\user\\Documents\\Computer Science\\PartII Project\\Java\\workspace\\" +
				"Photon Mapping\\rMDiffPts\\";
		String pMDiff = "C:\\Users\\user\\Documents\\Computer Science\\PartII Project\\Java\\workspace\\" +
				"Photon Mapping\\pMDiffPts\\";
		String rMDiffStat = "C:\\Users\\user\\Documents\\Computer Science\\PartII Project\\Java\\workspace\\" +
				"Photon Mapping\\rMDiffStat\\";
		String pMDiffStat = "C:\\Users\\user\\Documents\\Computer Science\\PartII Project\\Java\\workspace\\" +
				"Photon Mapping\\pMDiffStat\\";

		File mayaDir = new File(mayaPNG);

		for (File mayaImg : mayaDir.listFiles()){

			try{
				FileWriter rMWriter = new FileWriter(rMDiff + mayaImg.getName() + ".csv");
				FileWriter pMWriter = new FileWriter(pMDiff + mayaImg.getName() + ".csv");
				File photonImg = new File(photonPNG + mayaImg.getName());
				File rayImg = new File(rayPNG + mayaImg.getName());		
				BufferedImage mayaImage, photonImage, rayImage;

				try {
					mayaImage = ImageIO.read(mayaImg);
					photonImage = ImageIO.read(photonImg);
					rayImage = ImageIO.read(rayImg);

					assert rayImage.getWidth() == photonImage.getWidth();
					assert rayImage.getWidth() == mayaImage.getWidth();
					assert rayImage.getHeight() == photonImage.getHeight();
					assert rayImage.getHeight() == mayaImage.getHeight();

					BufferedImage pMDiffImage = new BufferedImage(rayImage.getWidth(), rayImage.getHeight(),
							BufferedImage.TYPE_INT_RGB);
					BufferedImage rMDiffImage = new BufferedImage(rayImage.getWidth(), rayImage.getHeight(),
							BufferedImage.TYPE_INT_RGB);

					int[] pMMap = new int[rayImage.getWidth()*rayImage.getHeight()];
					int[] rMMap = new int[rayImage.getWidth()*rayImage.getHeight()];

					Vector3D diff;
					double base = 127.5;
					double pMean = 0, rMean = 0;
					int zeros = 0, ones = 0;
					int zerosP = 0, onesP = 0;
					for (int row = 0; row < rayImage.getHeight(); row++){
						for (int column = 0; column < rayImage.getWidth(); column++){
							diff = new Colour(photonImage.getRGB(column, row)).sub(
									new Colour(mayaImage.getRGB(column, row))).plus(new Vector3D(base, base, base));
							pMMap[row*rayImage.getWidth()+column] = new Colour(diff.x, diff.y, diff.z).toRGB();
							pMean += (diff.x + diff.y + diff.z)/3;
							pMWriter.append(String.valueOf((diff.x+diff.y+diff.z)/3-base));
							if (Math.abs((diff.x+diff.y+diff.z)/3-base) < 1){
								onesP++;
								if (Math.abs((diff.x+diff.y+diff.z)/3-base) == 0){
									zerosP++;
								}
							}
							if (column%200 != 0){
								pMWriter.append(",");
							}
							else{
								pMWriter.append("\n");
							}

							diff = new Colour(rayImage.getRGB(column, row)).sub(
									new Colour(mayaImage.getRGB(column, row))).plus(new Vector3D(base, base, base));
							rMMap[row*rayImage.getWidth()+column] = new Colour(diff.x, diff.y, diff.z).toRGB();
							rMean += (diff.x + diff.y + diff.z)/3;
							rMWriter.append(String.valueOf((diff.x+diff.y+diff.z)/3-base));
							if (Math.abs((diff.x+diff.y+diff.z)/3-base) < 1){
								ones++;
								if (Math.abs((diff.x+diff.y+diff.z)/3-base) == 0){
									zeros++;
								}
							}
							if (column%200 != 0){
								rMWriter.append(",");
							}
							else{
								rMWriter.append("\n");
							}
						}
					}
					pMean /= rayImage.getHeight()*rayImage.getWidth();
					rMean /= rayImage.getHeight()*rayImage.getWidth();
					pMean -= base;
					rMean -= base;

					double pSD = 0, rSD = 0;

					for (int row = 0; row < rayImage.getHeight(); row++){
						for (int column = 0; column < rayImage.getWidth(); column++){
							diff = new Colour(pMMap[row*rayImage.getWidth()+column]);
							pSD += Math.pow((diff.x + diff.y + diff.z)/3 - base - pMean,2);

							diff = new Colour(rMMap[row*rayImage.getWidth()+column]);
							rSD += Math.pow((diff.x + diff.y + diff.z)/3 - base - rMean,2);
						}
					}

					pSD /= rayImage.getHeight()*rayImage.getWidth()-1;
					rSD /= rayImage.getHeight()*rayImage.getWidth()-1;
					pSD = Math.sqrt(pSD);
					rSD = Math.sqrt(rSD);

					FileWriter rMStatWriter = new FileWriter(rMDiffStat + mayaImg.getName() + ".txt");
					FileWriter pMStatWriter = new FileWriter(pMDiffStat + mayaImg.getName() + ".txt");

					rMStatWriter.append(mayaImg.getName() + " " + rMean + " " + rSD + " " + zeros + " " + ones);
					pMStatWriter.append(mayaImg.getName() + " " + pMean + " " + pSD + " " + zerosP + " " + onesP);

					System.err.println(mayaImg.getName() + " " + pMean + " " + pSD + " " + zerosP + " " + onesP);
					System.err.println(mayaImg.getName() + " " + rMean + " " + rSD + " " + zeros + " " + ones);

					rMWriter.flush();
					rMWriter.close();

					pMWriter.flush();
					pMWriter.close();

					rMStatWriter.flush();
					rMStatWriter.close();

					pMStatWriter.flush();
					pMStatWriter.close();

					// produce a RGB image from the hitMap
					pMDiffImage.setRGB(0, 0, rayImage.getWidth(), rayImage.getHeight(), pMMap, 0, rayImage.getWidth());
					rMDiffImage.setRGB(0, 0, rayImage.getWidth(), rayImage.getHeight(), rMMap, 0, rayImage.getWidth());
					// save the image on disk in the defined location
					try {
						File outputfile = new File(pMDiffPNG + mayaImg.getName());
						ImageIO.write(pMDiffImage, "png", outputfile);

						outputfile = new File(rMDiffPNG + mayaImg.getName());
						ImageIO.write(rMDiffImage, "png", outputfile);

						assertTrue(true);
					} catch (IOException e) {
						e.printStackTrace();
						fail();
					}
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			} catch (IOException e2){
				e2.printStackTrace();
			}
		}
	}

}
